package taskmanager

import (
	"context"
	"errors"
	"fmt"
	"time"

	"dev.ixmxm.top/rms/boot"
	"dev.ixmxm.top/rms/codes"
	"dev.ixmxm.top/rms/model"
	"dev.ixmxm.top/rms/utils/function"
	"dev.ixmxm.top/rms/utils/log"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

//初始化子任务ID索引
func (m *TaskManager) SubtaskIdInit(ctx context.Context) codes.Code {
	dbRes := m.db.Collection(ctx, fmt.Sprintf("%s_index", model.Subtask{}.TableName())).FindOne(ctx, bson.M{})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get subtaskId from db error:%s", dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		_, err := m.db.Collection(ctx, fmt.Sprintf("%s_index", model.Subtask{}.TableName())).InsertOne(ctx, bson.M{"id": 1})
		if err != nil {
			return codes.ErrDatabase.Wrap(err)
		}
	}
	return nil
}

//AddToDB 添加任务到数据库
func (m *TaskManager) AddSubtaskToDB(ctx context.Context, subtask *model.Subtask) (*model.Subtask, codes.Code) {
	if err := m.db.Collection(ctx, fmt.Sprintf("%s_index", subtask.TableName())).FindOneAndUpdate(ctx, bson.M{}, bson.M{"$inc": bson.M{"id": 1}}, &options.FindOneAndUpdateOptions{Projection: bson.M{"_id": 0}, Upsert: function.BoolPtr(true)}).Decode(&subtask); err != nil && !errors.Is(err, mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "insert subtask to db error,can not get index:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	_, errInsert := m.db.Collection(ctx, subtask.TableName()).InsertOne(ctx, subtask)
	if errInsert != nil {
		log.ErrorfWithContext(ctx, "insert subtask to db error:%s", errInsert.Error())
		return nil, codes.ErrDatabase.Wrap(errInsert)
	}
	return subtask, nil
}

//updateToDB 更新子任务到数据库
func (m *TaskManager) UpdateSubtaskToDB(ctx context.Context, subtask *model.Subtask) codes.Code {
	dbRes := m.db.Collection(ctx, model.Subtask{}.TableName()).FindOneAndReplace(ctx, bson.M{"id": subtask.Id}, subtask, &options.FindOneAndReplaceOptions{Upsert: function.BoolPtr(true)})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "update subtask to db error:%s", dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	return nil
}

//从数据库获得所有状态的子任务
func (m *TaskManager) GetAllStatusSubtasksFromDB(ctx context.Context, status []model.TaskStatus) ([]*model.Subtask, codes.Code) {
	dbRes, err := m.db.Collection(ctx, model.Subtask{}.TableName()).Find(ctx, bson.M{"status": bson.M{"$in": status}}, &options.FindOptions{Sort: bson.M{"index": 1}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all running tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	subtasks := make([]*model.Subtask, 0)
	if errBind := dbRes.All(ctx, &subtasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all running tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return subtasks, nil
}

//从数据库获得所有需要执行任务完成处理的子任务
func (m *TaskManager) GetAllFinishProcessSubtasksFromDB(ctx context.Context) ([]*model.Subtask, codes.Code) {
	dbRes, err := m.db.Collection(ctx, model.Subtask{}.TableName()).Find(ctx, bson.M{"status": model.TaskStatusFinish, "is_complete_process": 0})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all running tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	subtasks := make([]*model.Subtask, 0)
	if errBind := dbRes.All(ctx, &subtasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all running tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return subtasks, nil
}

//从数据库获得Robot需要执行任务完成处理的子任务
func (m *TaskManager) GetRobotFinishProcessSubtaskFromDB(ctx context.Context, agvId string) (*model.Subtask, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Subtask{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvId, "status": model.TaskStatusFinish, "is_complete_process": 0})

	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get all running subtask from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	subtask := new(model.Subtask)
	if errBind := dbRes.Decode(subtask); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign subtask from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return subtask, nil
}

//从数据库获得任务所有的子任务
func (m *TaskManager) GetAllSubtasksByTaskIdFromDB(ctx context.Context, taskId uint64) ([]*model.Subtask, codes.Code) {
	dbRes, err := m.db.Collection(ctx, model.Subtask{}.TableName()).Find(ctx, bson.M{"task_id": taskId}, &options.FindOptions{Sort: bson.M{"index": 1}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all  tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	subtasks := make([]*model.Subtask, 0)
	if errBind := dbRes.All(ctx, &subtasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all  tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return subtasks, nil
}

//从数据库获得子任务
func (m *TaskManager) GetSubtaskFromDB(ctx context.Context, subtaskId uint64) (*model.Subtask, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Subtask{}.TableName()).FindOne(ctx, bson.M{"id": subtaskId})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get all running subtask from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	subtask := new(model.Subtask)
	if errBind := dbRes.Decode(subtask); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign subtask from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return subtask, nil
}

//从数据库获得运行中的子任务，查询为空-报错
func (m *TaskManager) GetRunningSubtaskFromDB(ctx context.Context, agvId string) (*model.Subtask, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Subtask{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvId, "status": bson.M{"$in": model.TaskRunningStatus()}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get all running subtask from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	subtask := new(model.Subtask)
	if errBind := dbRes.Decode(subtask); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign subtask from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return subtask, nil
}

//从数据库获得运行中的子任务，查询为空-不报错
func (m *TaskManager) GetRunningSubtaskCanEmptyFromDB(ctx context.Context, agvId string) (*model.Subtask, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Subtask{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvId, "status": bson.M{"$in": model.TaskRunningStatus()}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get all running subtask from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, nil
	}
	subtask := new(model.Subtask)
	if errBind := dbRes.Decode(subtask); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign subtask from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return subtask, nil
}

//从数据库获得取消中和完成中的任务
func (m *TaskManager) GetUnCancelOrFinshSubtaskFromDB(ctx context.Context, agvId string) (*model.Subtask, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Subtask{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvId, "status": bson.M{"$in": model.TaskCancelingOrInfinshStatus()}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get all running subtask from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	subtask := new(model.Subtask)
	if errBind := dbRes.Decode(subtask); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign subtask from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return subtask, nil
}

//从数据库获得运行中的子任务
func (m *TaskManager) GetAllRunningSubtaskFromDB(ctx context.Context) ([]model.Subtask, codes.Code) {
	dbRes, err := m.db.Collection(ctx, model.Subtask{}.TableName()).Find(ctx, bson.M{"status": bson.M{"$in": model.TaskRunningStatus()}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all running subtask from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	subtasks := make([]model.Subtask, 0)
	if errBind := dbRes.All(ctx, &subtasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all status tasks from db error:%s", errBind.Error())
		return nil, codes.ErrTaskNotExists
	}
	return subtasks, nil
}

//从数据库获得目标点相同的子任务
func (m *TaskManager) GetAllSamePointSubtaskFromDB(ctx context.Context, mapName string, subtaskId uint64, targetId string) ([]model.Subtask, codes.Code) {
	dbRes, err := m.db.Collection(ctx, model.Subtask{}.TableName()).Find(ctx, bson.M{"target_site_id": targetId, "map_name": mapName, "status": bson.M{"$in": model.TaskRunStatus()}, "id": bson.M{"$ne": subtaskId}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all same point subtask from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, nil
	}
	subtasks := make([]model.Subtask, 0)
	if errBind := dbRes.All(ctx, &subtasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all same point subtask from db error:%s", errBind.Error())
		return nil, codes.ErrTaskNotExists
	}
	return subtasks, nil
}

//从数据库获一条待执行的子任务
func (m *TaskManager) GetWaitingSubtaskFromDB(ctx context.Context, agvId string) (*model.Subtask, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Subtask{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvId, "status": bson.M{"$in": model.TaskWaitingStatus()}}, &options.FindOneOptions{Sort: bson.M{"index": 1}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get all running subtask from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	subtask := new(model.Subtask)
	if errBind := dbRes.Decode(subtask); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign subtask from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return subtask, nil
}

//从数据库查找机器人指定状态的子任务
func (m *TaskManager) GetRobotStatusSubtaskFromDB(ctx context.Context, agvID string, status []model.TaskStatus) (*model.Subtask, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Subtask{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvID, "status": bson.M{"$in": status}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get robot:%s running task from db error:%s", agvID, dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	task := new(model.Subtask)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot running task from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return task, nil
}

//获取下一条子任务
func (m *TaskManager) GetNextSubtaskFromDB(ctx context.Context, subtask *model.Subtask) (*model.Subtask, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Subtask{}.TableName()).FindOne(ctx, bson.M{"task_id": subtask.TaskId, "index": subtask.Index + 1})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get all running subtask from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	subtask2 := new(model.Subtask)
	if errBind := dbRes.Decode(subtask2); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign subtask from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return subtask2, nil
}

//获取上一条子任务
func (m *TaskManager) GetFrontSubtaskFromDB(ctx context.Context, subtask *model.Subtask) (*model.Subtask, codes.Code) {
	index := subtask.Index - 1
	if index < 0 {
		return nil, nil
	}
	dbRes := m.db.Collection(ctx, model.Subtask{}.TableName()).FindOne(ctx, bson.M{"task_id": subtask.TaskId, "index": index})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get all running subtask from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	subtask2 := new(model.Subtask)
	if errBind := dbRes.Decode(subtask2); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign subtask from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return subtask2, nil
}

// 从数据库获得所有子任务
func (m *TaskManager) GetAllSubtaskFromDB(ctx context.Context) ([]model.Subtask, codes.Code) {
	dbRes, err := m.db.Collection(ctx, model.Subtask{}.TableName()).Find(ctx, bson.M{}, &options.FindOptions{Sort: bson.M{"created_time": -1}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all status tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	subtasks := make([]model.Subtask, 0)
	if errBind := dbRes.All(ctx, &subtasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all status tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return subtasks, nil
}

//更具Key值更新子任务
func (m *TaskManager) UpdateSubtaskKeyToDB(ctxTx context.Context, subtaskid uint64, key string, value model.TaskSubStatus) codes.Code {
	dbRes := m.db.Collection(ctxTx, model.Subtask{}.TableName()).FindOneAndUpdate(ctxTx, bson.M{"id": subtaskid}, bson.M{"$set": bson.M{key: value}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctxTx, "update task:%d to db error:%s", subtaskid, dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return codes.ErrTaskNotExists
	}
	// log.Warnf("Update Subtask substatus= %d", int(value))
	return nil
}
func (m *TaskManager) UpdateSubtaskKeyIntToDB(ctxTx context.Context, subtaskid uint64, key string, value int) codes.Code {
	dbRes := m.db.Collection(ctxTx, model.Subtask{}.TableName()).FindOneAndUpdate(ctxTx, bson.M{"id": subtaskid}, bson.M{"$set": bson.M{key: value}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctxTx, "update task:%d to db error:%s", subtaskid, dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return codes.ErrTaskNotExists
	}
	return nil
}
func (m *TaskManager) UpdateSubtaskKeyStringToDB(ctxTx context.Context, subtaskid uint64, key string, value string) codes.Code {
	dbRes := m.db.Collection(ctxTx, model.Subtask{}.TableName()).FindOneAndUpdate(ctxTx, bson.M{"id": subtaskid}, bson.M{"$set": bson.M{key: value}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctxTx, "update task:%d to db error:%s", subtaskid, dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return codes.ErrTaskNotExists
	}
	return nil
}

func (m *TaskManager) UpdateSubtaskLeftPathToDB(ctxTx context.Context, subtaskid uint64, key string, value *model.TrafficPaths) codes.Code {
	dbRes := m.db.Collection(ctxTx, model.Subtask{}.TableName()).FindOneAndUpdate(ctxTx, bson.M{"id": subtaskid}, bson.M{"$set": bson.M{key: value}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctxTx, "update task:%d to db error:%s", subtaskid, dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return codes.ErrTaskNotExists
	}
	return nil
}
func (m *TaskManager) UpdateSubtaskBlockInfoToDB(ctxTx context.Context, subtaskid uint64, agv_id, site string, task_id uint64, task_grade int32, block_start_time time.Time, external_grade int32) codes.Code {
	data := bson.M{"block_agv": agv_id}
	data["block_agv_site"] = site
	data["block_task"] = task_id
	data["block_task_grade"] = task_grade
	data["block_start_time"] = block_start_time
	data["external_grade"] = external_grade
	dbRes := m.db.Collection(ctxTx, model.Subtask{}.TableName()).FindOneAndUpdate(ctxTx, bson.M{"id": subtaskid}, bson.M{"$set": data})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctxTx, "update task:%d to db error:%s", subtaskid, dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return codes.ErrTaskNotExists
	}
	return nil
}
func (m *TaskManager) UpdateAllSubtaskStatusToDB(ctxTx context.Context, currentSubTask *model.Subtask, subtaskStatus model.TaskStatus) codes.Code {
	log.Infof("更新其它子任务状态 subtask:%d status:%s", currentSubTask.Id, m.taskStatusEnum[int(subtaskStatus)])
	data := bson.M{"status": subtaskStatus}
	dbRes := m.db.Collection(ctxTx, model.Subtask{}.TableName()).FindOneAndUpdate(ctxTx, bson.M{"task_id": currentSubTask.TaskId}, bson.M{"$set": data})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctxTx, "update all subtask status by taskId:%d to db error:%s", currentSubTask.TaskId, dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return nil
	}
	return nil
}

// 数据库更新子任务状态(必须使用事物、根据子任务的状态更改任务状态、isFirstRun:该子任务是否为第一次执行)
func (m *TaskManager) UpdateSubtaskStatusToDB(ctxTx *boot.TxContext, subtaskId uint64, subtaskStatus model.TaskStatus, isFirstRun bool) codes.Code {
	log.Infof("更新子任务状态 subtask:%d status:%s", subtaskId, m.taskStatusEnum[int(subtaskStatus)])

	//获取子任务
	subtask, err := m.GetSubtaskFromDB(ctxTx, subtaskId)
	if err != nil {
		return err
	}
	if subtask == nil {
		return codes.ErrTaskNotExists
	}

	data := bson.M{"status": subtaskStatus}
	if isFirstRun {
		data["start_time"] = time.Now()
	}
	if subtaskStatus == model.TaskStatusRunning {
		data["task_operate_flag"] = 0
	}

	isUpdateSubtaskStatus := false      //是否更新子任务类型
	isUpdateTaskStatus := false         //是否更新任务类型
	taskStatus := model.TaskStatusError //要更新成的任务状态
	isDeleteSubtask := false            //是否需要删除所有子任务
	isClearTask := false                //是否需要解除任务绑定
	//isClearMainTask := false            //是否需要解除主任务绑定
	//14种状态变更   登记、分配、解析，不做处理
	switch subtaskStatus {
	case model.TaskStatusRunning:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusInFinish:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusFinish:
		isUpdateSubtaskStatus = true
		data["finish_time"] = time.Now()
		//不需要处理任务，有个线程单独处理
		// isDeleteSubtask = true
		// isClearTask = true

	case model.TaskStatusCanceling:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusCanceled:
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus
		isDeleteSubtask = true
		isClearTask = true

	case model.TaskStatusPausing:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusPaused:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusContinuing:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusCharging:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusInTheTransit:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStasusAvoid:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusError:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	}

	//更新子任务类型
	if isUpdateSubtaskStatus {
		dbRes := m.db.Collection(ctxTx, model.Subtask{}.TableName()).FindOneAndUpdate(ctxTx, bson.M{"id": subtaskId}, bson.M{"$set": data})
		if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
			log.ErrorfWithContext(ctxTx, "update task:%d to db error:%s", subtaskId, dbRes.Err().Error())
			return codes.ErrDatabase.Wrap(dbRes.Err())
		}
		if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
			//log.Errorf("can not find task:%d",id)
			return codes.ErrTaskNotExists
		}
	}

	//更新任务类型
	if isUpdateTaskStatus {
		err := m.UpdateTaskStatusToDB(ctxTx, subtask.TaskId, taskStatus)
		if err != nil {
			return err
		}
	}

	//删除所有子任务
	if isDeleteSubtask {
		err := m.DeleteSubtasksToDB(ctxTx, subtask.TaskId)
		if err != nil {
			return err
		}
	}

	//解除任务绑定
	if isClearTask {
		//获取任务
		task, err := m.GetTaskFromDB(ctxTx, subtask.TaskId)
		if err != nil {
			return err
		}
		if task == nil {
			return codes.ErrTaskNotExists
		}
		if task.MainTaskCode == "" {
			err := m.DeleteMainTaskByAgvIdToDB(ctxTx, task.AgvId)
			log.Info("*************delete no main task code task*************")
			if err != nil {
				return err
			}
		} else {
			err = m.UpdateMainTaskIdToDB(ctxTx, task.MainTaskCode, 0, task.AgvId)
			// err = m.AddMainTaskToDB(ctxTx, task.MainTaskCode, 0, task.AgvId)
			if err != nil {
				return err
			}
		}

	}

	return nil
}

func (m *TaskManager) UpdateFocuseSubtaskStatusToDB(ctxTx *boot.TxContext, subtaskId uint64, subtaskStatus model.TaskStatus, isFirstRun bool, completeType model.CompleteType) codes.Code {
	log.Infof("更新子任务状态 subtask:%d status:%s", subtaskId, m.taskStatusEnum[int(subtaskStatus)])

	//获取子任务
	subtask, err := m.GetSubtaskFromDB(ctxTx, subtaskId)
	if err != nil {
		return err
	}
	if subtask == nil {
		return codes.ErrTaskNotExists
	}

	data := bson.M{"status": subtaskStatus}
	if isFirstRun {
		data["start_time"] = time.Now()
	}
	if subtaskStatus == model.TaskStatusRunning {
		data["task_operate_flag"] = 0
	}

	isUpdateSubtaskStatus := false      //是否更新子任务类型
	isUpdateTaskStatus := false         //是否更新任务类型
	taskStatus := model.TaskStatusError //要更新成的任务状态
	isDeleteSubtask := false            //是否需要删除所有子任务
	isClearTask := false                //是否需要解除任务绑定
	//isClearMainTask := false            //是否需要解除主任务绑定
	//14种状态变更   登记、分配、解析，不做处理
	switch subtaskStatus {
	case model.TaskStatusRunning:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusInFinish:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusFinish:
		isUpdateSubtaskStatus = true
		data["finish_time"] = time.Now()
		//不需要处理任务，有个线程单独处理
		// isDeleteSubtask = true
		// isClearTask = true

	case model.TaskStatusCanceling:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusCanceled:
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus
		isDeleteSubtask = true
		isClearTask = true

	case model.TaskStatusPausing:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusPaused:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusContinuing:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusCharging:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusInTheTransit:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStasusAvoid:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	case model.TaskStatusError:
		isUpdateSubtaskStatus = true
		isUpdateTaskStatus = true
		taskStatus = subtaskStatus

	}

	//更新子任务类型
	if isUpdateSubtaskStatus {
		dbRes := m.db.Collection(ctxTx, model.Subtask{}.TableName()).FindOneAndUpdate(ctxTx, bson.M{"id": subtaskId}, bson.M{"$set": data})
		if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
			log.ErrorfWithContext(ctxTx, "update task:%d to db error:%s", subtaskId, dbRes.Err().Error())
			return codes.ErrDatabase.Wrap(dbRes.Err())
		}
		if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
			//log.Errorf("can not find task:%d",id)
			return codes.ErrTaskNotExists
		}
	}

	//更新任务类型
	if isUpdateTaskStatus {
		err := m.UpdateFocuseTaskStatusToDB(ctxTx, subtask.TaskId, taskStatus, completeType)
		if err != nil {
			return err
		}
	}

	//删除所有子任务
	if isDeleteSubtask {
		err := m.DeleteSubtasksToDB(ctxTx, subtask.TaskId)
		if err != nil {
			return err
		}
	}

	//解除任务绑定
	if isClearTask {
		//获取任务
		task, err := m.GetTaskFromDB(ctxTx, subtask.TaskId)
		if err != nil {
			return err
		}
		if task == nil {
			return codes.ErrTaskNotExists
		}
		if task.MainTaskCode == "" {
			err := m.DeleteMainTaskByAgvIdToDB(ctxTx, task.AgvId)
			log.Info("*************delete no main task code task*************")
			if err != nil {
				return err
			}
		} else {
			err = m.UpdateMainTaskIdToDB(ctxTx, task.MainTaskCode, 0, task.AgvId)
			// err = m.AddMainTaskToDB(ctxTx, task.MainTaskCode, 0, task.AgvId)
			if err != nil {
				return err
			}
		}

	}

	return nil
}

// 向数据库更新子任务完成处理标志
func (m *TaskManager) UpdateSubtaskCompletProcessToDB(ctx context.Context, subtaskid uint64, isCompletProcess int) codes.Code {
	dbRes := m.db.Collection(ctx, model.Subtask{}.TableName()).FindOneAndUpdate(ctx, bson.M{"id": subtaskid}, bson.M{"$set": bson.M{"is_complete_process": isCompletProcess}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "update task:%d to db error:%s", subtaskid, dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return codes.ErrTaskNotExists
	}
	return nil
}

// 向数据库删除任务下所有子任务
func (m *TaskManager) DeleteSubtasksToDB(ctx context.Context, taskid uint64) codes.Code {
	log.Infof("开始删除任务(%d)下的所有子任务", taskid)
	_, err := m.db.Collection(ctx, model.Subtask{}.TableName()).DeleteMany(ctx, bson.M{"task_id": taskid})
	if err != nil {
		log.ErrorfWithContext(ctx, "Delete Many subtasks from db. taskId:%d error:%s", taskid, err.Error())
		return codes.ErrDatabase.Wrap(err)
	}
	return nil
}
